package com.kummuna.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONObject;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;
import com.kummuna.R;
import com.kummuna.util.json.DirectionsJSONParser;

import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class RouteMap extends Activity implements LocationListener {

	GoogleMap map;
	MapView mapView;
	ArrayList<LatLng> markerPoints;
	// TextView tvDistance;
	String result;
	// float[] distance = new float[1];
	private String distance;
	private String duration;
	private Location locationPresent;
	private LatLng source;
	private LatLng destination;
	private String latitudeFormAddWaterLeak;
	private String longtitudeFormAddWaterLeak;
	private String topicFormAddWaterLeak;
	private String detailFormAddWaterLeak;
	private String timeFormAddWaterLeak;
	private int flagMapGetPath = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_detectivemap);

		markerPoints = new ArrayList<LatLng>();

		setUpMapIfNeeded();
		setUpLocation();
		map.setInfoWindowAdapter(new InfoWindowAdapter() {

			@Override
			public View getInfoWindow(Marker arg0) {
				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public View getInfoContents(Marker arg0) {
				// Getting view from the layout file info_window_layout
				View v = getLayoutInflater()
						.inflate(R.layout.info_window, null);

				// Getting the position from the marker
				LatLng latLng = arg0.getPosition();

				TextView tv_Topic = (TextView) v.findViewById(R.id.tv_topic);
				TextView tv_Date = (TextView) v.findViewById(R.id.tv_date);
				TextView tv_Detail = (TextView) v.findViewById(R.id.tv_detail);
				TextView tv_Status = (TextView) v.findViewById(R.id.tv_status);

				// Getting reference to the TextView to set topic
				//tv_Topic.setText("" + latLng.latitude);
				tv_Topic.setText(topicFormAddWaterLeak);
				// Getting reference to the TextView to set date
				tv_Date.setText(timeFormAddWaterLeak);
				// Getting reference to the TextView to set detail
				tv_Detail.setText(detailFormAddWaterLeak);
				// Getting reference to the TextView to set status
				tv_Status.setText("" + latLng.longitude);

				// Returning the view containing InfoWindow contents
				return v;

			}
		});
		
		Bundle extras = getIntent().getExtras();		

		if (extras != null) {
			topicFormAddWaterLeak = extras.getString("topic");
			detailFormAddWaterLeak = extras.getString("detail");
			latitudeFormAddWaterLeak = extras.getString("latitude");
			longtitudeFormAddWaterLeak = extras.getString("longtitude");
			timeFormAddWaterLeak = extras.getString("time");
			
			LatLng latLng = new LatLng(Double.parseDouble(latitudeFormAddWaterLeak),Double.parseDouble(longtitudeFormAddWaterLeak));
			
			Context context = getApplicationContext();
			CharSequence text = "Routh Path!";
			int duration = Toast.LENGTH_LONG;

			Toast toast = Toast.makeText(context, text, duration);
			toast.show();

			markerPoints.add(latLng);

			MarkerOptions markerOptions = new MarkerOptions();
			markerOptions.position(latLng);
//			markerOptions.title(latLng.latitude + " : " + latLng.longitude);
//			result = "Start \nLatitude = " + latLng.latitude
//					+ " Longitude = " + latLng.longitude;

			if (markerPoints.size() == 1) {
				markerOptions.icon(BitmapDescriptorFactory
						.defaultMarker(BitmapDescriptorFactory.HUE_RED));
//				result = "Start \nLatitude = " + latLng.latitude
//						+ " Longitude = " + latLng.longitude + "\n";
				// tvDistance.setText(result);
			}

			CameraPosition cameraPosition = new CameraPosition.Builder()
					.target(latLng).zoom(13).bearing(-30).tilt(90).build();

			// map.animateCamera(CameraUpdateFactory.newLatLng(latLng));
			map.animateCamera(CameraUpdateFactory
					.newCameraPosition(cameraPosition));

			// Adding marker on the GoogleMap
			Marker marker = map.addMarker(markerOptions);

			// Showing InfoWindow on the GoogleMap
			marker.showInfoWindow();
			
			

			if (markerPoints.size() >= 1) {
				// LatLng origin = markerPoints.get(0);
				destination = markerPoints.get(0);

				// get Source from Location
				source = new LatLng(getLocationPresent().getLatitude(),
						getLocationPresent().getLongitude());

				getPath(source, destination);

			}
		}
		
		map.setOnMapLongClickListener(new OnMapLongClickListener() {

			@Override
			public void onMapLongClick(LatLng latLng) {
				
				Intent addMarkWater = new Intent(RouteMap.this,AddWaterLeak.class);
				addMarkWater.putExtra("latitude", latLng.latitude+"");
				addMarkWater.putExtra("longtitude", latLng.longitude+"");				
				
				startActivity(addMarkWater);
				
			}
		});
	}

	private void setUpMapIfNeeded() {
		if (map == null) {
			map = ((MapFragment) getFragmentManager()
					.findFragmentById(R.id.map)).getMap();

			if (map != null) {
				setUpMap();
			}
		}
	}

	private void setUpMap() {
		map.setMyLocationEnabled(true);
		map.getUiSettings().setCompassEnabled(true);
		map.setTrafficEnabled(false);
	}

	private void setUpLocation() {

		// Getting Google Play availability status
		int status = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(getBaseContext());

		// Showing status
		if (status != ConnectionResult.SUCCESS) { // Google Play Services are
													// not available

			int requestCode = 10;
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this,
					requestCode);
			dialog.show();

		} else { // Google Play Services are available

			// Getting LocationManager object from System Service
			// LOCATION_SERVICE
			LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

			// Creating a criteria object to retrieve provider
			Criteria criteria = new Criteria();

			// Getting the name of the best provider
			String provider = locationManager.getBestProvider(criteria, true);

			// Getting Current Location
			Location location = locationManager.getLastKnownLocation(provider);

			if (location != null) {
				onLocationChanged(location);
				// set location Present
				setLocationPresent(location);
			}

			locationManager.requestLocationUpdates(provider, 2000, 1, this);
		}
	}

	private void getPath(LatLng origin, LatLng dest) {
		// Getting URL to the Google Directions API
		String url = getDirectionsUrl(origin, dest);

		DownloadTask downloadTask = new DownloadTask();

		// Start downloading json data from Google Directions
		// API
		downloadTask.execute(url);
	}

	private String getDirectionsUrl(LatLng origin, LatLng dest) {
		// Origin of route
		String str_origin = "origin=" + origin.latitude + ","
				+ origin.longitude;

		// Destination of route
		String str_dest = "destination=" + dest.latitude + "," + dest.longitude;

		// Sensor enabled
		String sensor = "sensor=false";

		// Building the parameters to the web service
		String parameters = str_origin + "&" + str_dest + "&" + sensor;

		// Output format
		String output = "json";

		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"
				+ output + "?" + parameters;

		return url;
	}

	/** A method to download json data from url */
	private String downloadUrl(String strUrl) throws IOException {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try {
			URL url = new URL(strUrl);

			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();

			// Connecting to url
			urlConnection.connect();

			// Reading data from url
			iStream = urlConnection.getInputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(
					iStream));

			StringBuffer sb = new StringBuffer();

			String line = "";
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			data = sb.toString();

			br.close();

		} catch (Exception e) {
			Log.d("Exception while downloading url", e.toString());
		} finally {
			iStream.close();
			urlConnection.disconnect();
		}
		return data;
	}

	/** A class to download data from Google Directions URL */
	private class DownloadTask extends AsyncTask<String, Void, String> {

		// Downloading data in non-ui thread
		@Override
		protected String doInBackground(String... url) {

			// For storing data from web service
			String data = "";

			try {
				// Fetching the data from web service
				data = downloadUrl(url[0]);
			} catch (Exception e) {
				Log.d("Background Task", e.toString());
			}
			return data;
		}

		// Executes in UI thread, after the execution of
		// doInBackground()
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);

			ParserTask parserTask = new ParserTask();

			// Invokes the thread for parsing the JSON data
			parserTask.execute(result);
		}
	}

	/** A class to parse the Google Directions in JSON format */
	private class ParserTask extends
			AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

		// Parsing the data in non-ui thread
		@Override
		protected List<List<HashMap<String, String>>> doInBackground(
				String... jsonData) {

			JSONObject jObject;
			List<List<HashMap<String, String>>> routes = null;

			try {
				jObject = new JSONObject(jsonData[0]);
				DirectionsJSONParser parser = new DirectionsJSONParser();

				// Starts parsing data
				routes = parser.parse(jObject);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return routes;
		}

		// Executes in UI thread, after the parsing process
		@Override
		protected void onPostExecute(List<List<HashMap<String, String>>> result) {
			ArrayList<LatLng> points = null;
			PolylineOptions lineOptions = null;
			// MarkerOptions markerOptions = new MarkerOptions();
			String distance = "";
			String duration = "";

			if (result.size() < 1) {
				Toast.makeText(getBaseContext(), "No Points",
						Toast.LENGTH_SHORT).show();
				return;
			}

			// Traversing through all the routes
			for (int i = 0; i < result.size(); i++) {
				points = new ArrayList<LatLng>();
				lineOptions = new PolylineOptions();

				// Fetching i-th route
				List<HashMap<String, String>> path = result.get(i);

				// Fetching all the points in i-th route
				for (int j = 0; j < path.size(); j++) {
					HashMap<String, String> point = path.get(j);

					if (j == 0) { // Get distance from the list
						distance = (String) point.get("distance");
						continue;
					} else if (j == 1) { // Get duration from the list
						duration = (String) point.get("duration");
						continue;
					}

					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);

					points.add(position);
				}

				// Adding all the points in the route to LineOptions
				lineOptions.addAll(points);
				lineOptions.width(2);
				lineOptions.color(Color.RED);
			}

			// Drawing polyline in the Google Map for the i-th route
			map.addPolyline(lineOptions);
			setDistance(distance);
			setDuration(duration);
			// tvDistance.setText("Distance:" + getDistance() + ", Duration:"
			// + getDuration());

		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id._clear:
			map.clear();
			flagMapGetPath = 0;
			// tvDistance.setText("");
			markerPoints.clear();
			break;
		case R.id._normal:
			map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
			break;
		case R.id._satellite:
			map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
			break;
		case R.id._hybrid:
			map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.

		getMenuInflater().inflate(R.menu.main, menu);

		return true;
	}

	@Override
	public void onLocationChanged(Location location) {
		// TextView tvLocation = (TextView) findViewById(R.id.tv_location);

		// Getting latitude
		double latitude = location.getLatitude();

		// Getting longitude
		double longitude = location.getLongitude();

		// Creating a LatLng object for the current location
		LatLng latLng = new LatLng(latitude, longitude);

		// Showing the current location in Google Map
		map.moveCamera(CameraUpdateFactory.newLatLng(latLng));

		// Zoom in the Google Map
		map.animateCamera(CameraUpdateFactory.zoomTo(15));

		// Setting latitude and longitude in the TextView tv_location
		// tvLocation.setText("Latitude:" + latitude + ", Longitude:" +
		// longitude);
		if (destination != null && flagMapGetPath != 0)
			getPath(latLng, destination);

	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub

	}

	public void nextpage(View view) {
		Intent mapIntent = new Intent(getApplicationContext(),
				DetectShortpath.class);
		mapIntent.putExtra("latitudePosition", getLocationPresent().getLatitude() +"");
		mapIntent.putExtra("longtitudePosition", getLocationPresent().getLongitude() +"");
		startActivity(mapIntent);
	}

	public String getDistance() {
		return distance;
	}

	public void setDistance(String distance) {
		this.distance = distance;
	}

	public String getDuration() {
		return duration;
	}

	public void setDuration(String duration) {
		this.duration = duration;
	}

	public Location getLocationPresent() {
		return locationPresent;
	}

	public void setLocationPresent(Location locationPresent) {
		this.locationPresent = locationPresent;
	}
}